package com.wangsh.train.common.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import javax.annotation.Resource;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 模拟浏览器请求任何一个网址
 * @author Wangsh
 */
@Component("httpUtil")
public class HttpUtil
{
	@Resource
	private FileUtil fileUtil ;
	@Resource
	private CallCommandUtil commandUtil ;
	@Resource
	private SpringEmailUtil springEmailUtil ; 
	
	public class TrustAnyHostnameVerifier implements HostnameVerifier
	{
		public boolean verify(String hostname, SSLSession session)
		{
			// 直接返回true
			return true;
		}
	}
	
	/**
	 * 输入一个url,
	 * 返回这个url对应的html代码
	 * 
	 * @param urlStr:网址
	 * @param headerMap 请求头
	 * @param paramsMap 请求体
	 * @param responseMap 响应头
	 * @return 返回网址对应的html代码
	 */
	public String methodGet(String urlStr,Map<String,String> headerMap,
			Map<String, String> paramsMap,Map<String, String> responseMap)
	{
		//ConstatFinalUtil.SYS_LOGGER.info("--methodGet--url:{}",urlStr);
		//如果是https协议
//		if(urlStr.startsWith("https"))
//		{
//			return this.methodHttpsGet(urlStr,headerMap, paramsMap,responseMap);
//		}
		StringBuffer sb = new StringBuffer() ; 
		StringBuffer paramssb = new StringBuffer();
		paramssb.append(urlStr);
		if (!paramssb.toString().endsWith("?") && paramsMap.size() > 0)
		{
			paramssb.append("?");
		}
		for (Iterator iterator = paramsMap.entrySet().iterator(); iterator
				.hasNext();)
		{
			Map.Entry me = (Map.Entry) iterator.next();
			String key = me.getKey() + "" ; 
			String value = me.getValue() + "" ;
			key = key.trim() ; 
			value = value.trim() ; 
			paramssb.append(key + "=" + value + "&");
		}

		if (paramssb.toString().endsWith("&"))
		{
			paramssb.delete(paramssb.length() - 1, paramssb.length());
		}
		
		// 连续请求多次
		for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++)
		{
			/* 起始时间戳 */
			long st = System.currentTimeMillis() ; 
			/* 结束时间戳 */
			long ed = 0 ; 
			BufferedReader br = null ; 
			try
			{
				sb.delete(0, sb.length());
				URL url = new URL(paramssb.toString());
				HttpURLConnection connection = (HttpURLConnection) this.newConnection(url, headerMap); 
				
				HttpURLConnection.setFollowRedirects(false);
				connection.setInstanceFollowRedirects(false);
				
				/* Post请求,必须加以下操作 */
				connection.setRequestMethod("GET");
				
				/* 设置公共的请求头 */
				this.setCommonHeader(headerMap,connection);
				
				/* 设置请求头 */
				for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ; 
					String value = me.getValue() + "" ;
					key = key.trim() ; 
					value = value.trim() ; 
					if(!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE))
					{
						connection.setRequestProperty(key, value);
					}
				}
				
				/* 获取网址对应的输入流和输出流 */
				InputStream is = connection.getInputStream() ;
				
				//响应码成功
				if(connection.getResponseCode() == 200)
				{
					br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
				}else
				{
					if(connection.getErrorStream() != null)
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}else
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}
				}
				
				String line = "" ; 
				while((line = br.readLine()) != null)
				{
					sb.append(line);
				}
				
				/* 放置响应头 */
				this.responseHeaderSave(headerMap,responseMap, connection);
				
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				//ConstatFinalUtil.SYS_LOGGER.info("响应体:{}",sb.toString());
				ConstatFinalUtil.SYS_LOGGER.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",i,(ed-st),urlStr,headerMap,paramsMap,responseMap);
				/* 检查网络 */
				this.noNetWork(true);
				/* 请求成功就退出 */
				break ;
			}catch(UnknownHostException | SocketTimeoutException e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
				/* 检查网络 */
				this.noNetWork(false);
			}catch (Exception e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
			}finally
			{
				/* 关闭流 */
				this.fileUtil.closeCharAll(br, null);
			}
			
			//重试机制
			if("false".equalsIgnoreCase(headerMap.get("retry")))
			{
				/* 默认不重试 */
				break ; 
			}
		}
		return sb.toString() ; 
	}
	
	/**
	 * 输入一个url,
	 * 返回这个url对应的html代码
	 * 
	 *@param urlStr:网址
	 * @param headerMap 请求头
	 * @param paramsMap 请求体
	 * @param responseMap 响应头
	 * @return 返回网址对应的html代码
	 */
	public String methodPost(String urlStr,Map<String,String> headerMap,
			Map<String, String> paramsMap,Map<String, String> responseMap)
	{
		//如果是https协议
//		if(urlStr.startsWith("https"))
//		{
//			return this.methodHttpsPost(urlStr,headerMap, paramsMap,responseMap);
//		}
		StringBuffer sb = new StringBuffer() ; 
		// 连续请求多次
		for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++)
		{
			/* 起始时间戳 */
			long st = System.currentTimeMillis() ; 
			/* 结束时间戳 */
			long ed = 0 ; 
			BufferedReader br = null ; 
			BufferedWriter bw = null ; 
			try
			{
				URL url = new URL(urlStr);
				HttpURLConnection connection = (HttpURLConnection) this.newConnection(url, headerMap);  ; 
				
				HttpURLConnection.setFollowRedirects(false);
				connection.setInstanceFollowRedirects(false);
				
				/* Post请求,必须加以下操作 */
				connection.setDoOutput(true);
				connection.setDoInput(true);
				connection.setRequestMethod("POST");
				
				/* 设置公共的请求头 */
				this.setCommonHeader(headerMap,connection);
				/* 设置请求头 */
				for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ; 
					String value = me.getValue() + "" ;
					key = key.trim() ; 
					value = value.trim() ; 
					if(!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE))
					{
						connection.setRequestProperty(key, value);
					}
				}
				/* 获取网址对应的输入流和输出流 */
				OutputStream os = connection.getOutputStream() ;
				bw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
				
				/* 先向服务器写数据
				 * 如何将我们的参数写到输出流呢???
				 * 得遵循HTTP协议,看浏览器怎么做,我们也怎么做
				 * 
				 * URL get中的字符串
				 * method=submit&email=aaa&password=bbbb
				 *  */
				StringBuffer paramSb = new StringBuffer() ; 
				for (Iterator iterator = paramsMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + ""; 
					String value = me.getValue() + "" ;
					key = key.trim();
					value = value.trim() ; 
					if (key.equals(""))
					{
						paramSb.append(value);
					}else {
						paramSb.append(key + "=" + value + "&");
					}
				}
				/*
				 * method=submit&email=aaa&password=bbbb
				 * email=bb&method=submit&password=cc
				 * */
				bw.write(paramSb.toString());
				bw.flush();
				bw.close();
				
				/* 获取网址对应的输入流和输出流 */
				InputStream is = connection.getInputStream() ;
				
				//响应码成功
				if(connection.getResponseCode() == 200)
				{
					br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
				}else
				{
					if(connection.getErrorStream() != null)
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}else
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}
				}
				
				String line = "" ; 
				while((line = br.readLine()) != null)
				{
					sb.append(line);
				}
				
				responseHeaderSave(headerMap,responseMap, connection);
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				//ConstatFinalUtil.SYS_LOGGER.info("响应体:{}",sb.toString());
				ConstatFinalUtil.SYS_LOGGER.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",i,(ed-st),urlStr,headerMap,paramsMap,responseMap);
				/* 检查网络 */
				this.noNetWork(true);
				/* 请求成功就退出 */
				break ;
			}catch(UnknownHostException | SocketTimeoutException e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
				/* 检查网络 */
				this.noNetWork(false);
			}catch (Exception e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
			}finally
			{
				/* 关闭流 */
				this.fileUtil.closeCharAll(br, null);
			}
			
			if("false".equalsIgnoreCase(headerMap.get("retry")))
			{
				/* 默认不重试 */
				break ; 
			}
		}
		return sb.toString() ; 
	}
	
	
	
	/**
	 * 输入一个url,
	 * 返回这个url对应的html代码
	 * 
	 * @param urlStr:网址
	 * @param headerMap 请求头
	 * @param paramsMap 请求体
	 * @param responseMap 响应头
	 * @return 返回网址对应的html代码
	 */
	public String methodHttpsGet(String urlStr,Map<String,String> headerMap,
			Map<String, String> paramsMap,Map<String, String> responseMap)
	{
		//ConstatFinalUtil.SYS_LOGGER.info("--methodGet--url:{}",urlStr);
		StringBuffer sb = new StringBuffer() ; 
		
		StringBuffer paramssb = new StringBuffer();
		paramssb.append(urlStr);
		if (!paramssb.toString().endsWith("?") && paramsMap.size() > 0)
		{
			paramssb.append("?");
		}
		for (Iterator iterator = paramsMap.entrySet().iterator(); iterator
				.hasNext();)
		{
			Map.Entry me = (Map.Entry) iterator.next();
			String key = me.getKey() + "" ; 
			String value = me.getValue() + "" ;
			key = key.trim() ; 
			value = value.trim() ; 
			paramssb.append(key + "=" + value + "&");
		}

		if (paramssb.toString().endsWith("&"))
		{
			paramssb.delete(paramssb.length() - 1, paramssb.length());
		}
		// 连续请求多次
		for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++)
		{
			/* 起始时间戳 */
			long st = System.currentTimeMillis() ; 
			/* 结束时间戳 */
			long ed = 0 ; 
			BufferedReader br = null ; 
			try
			{
				/*========https配置开始=========*/
				// Create a trust manager that does not validate certificate chains
				TrustManager[] trustAllCerts = new TrustManager[]
				{ new X509TrustManager()
				{
					public X509Certificate[] getAcceptedIssuers()
					{
						return null;
					}
	
					public void checkClientTrusted(X509Certificate[] certs, String authType)
					{
					}
	
					public void checkServerTrusted(X509Certificate[] certs, String authType)
					{
					}
				} };
				
				// Install the all-trusting trust manager
				SSLContext sc = SSLContext.getInstance("TLS");
				sc.init(null, trustAllCerts, new SecureRandom());
				HttpsURLConnection
						.setDefaultSSLSocketFactory(sc.getSocketFactory());
				/*========https配置结束=========*/
				URL url = new URL(paramssb.toString());
				HttpsURLConnection connection = (HttpsURLConnection) this.newConnection(url, headerMap); 
				/* ==connection常见的配置== */
				connection.setHostnameVerifier(new TrustAnyHostnameVerifier());
				
				HttpURLConnection.setFollowRedirects(false);
				connection.setInstanceFollowRedirects(false);
				
				/* Post请求,必须加以下操作 */
				connection.setRequestMethod("GET");
				
				/* 设置公共的请求头 */
				this.setCommonHeader(headerMap,connection);
				/* 设置请求头 */
				for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ; 
					String value = me.getValue() + "" ;
					key = key.trim() ; 
					value = value.trim() ; 
					if(!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE))
					{
						connection.setRequestProperty(key, value);
					}
				}
				/* 获取网址对应的输入流和输出流 */
				InputStream is = connection.getInputStream() ;
				
				//响应码成功
				if(connection.getResponseCode() == 200)
				{
					br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
				}else
				{
					if(connection.getErrorStream() != null)
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}else
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}
				}
				
				String line = "" ; 
				while((line = br.readLine()) != null)
				{
					sb.append(line);
				}
				
				/* 放置响应头 */
				this.responseHeaderSave(headerMap,responseMap, connection);
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				//ConstatFinalUtil.SYS_LOGGER.info("响应体:{}",sb.toString());
				ConstatFinalUtil.SYS_LOGGER.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",i,(ed-st),urlStr,headerMap,paramsMap,responseMap);
				/* 检查网络 */
				this.noNetWork(true);
				/* 请求成功就退出 */
				break ;
			}catch(UnknownHostException | SocketTimeoutException e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
				/* 检查网络 */
				this.noNetWork(false);
			}catch (Exception e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
			}finally
			{
				/* 关闭流 */
				this.fileUtil.closeCharAll(br, null);
			}
			
			//重试机制
			if("false".equalsIgnoreCase(headerMap.get("retry")))
			{
				/* 默认不重试 */
				break ; 
			}
		}
		return sb.toString() ; 
	}
	
	/**
	 * HttpsPost请求
	 * @param headerMap 请求头参数
	 * @param paramsMap 请求体参数
	 * @return
	 */
	public String methodHttpsPost(String urlStr,Map<String, String> headerMap,
			Map<String, String> paramsMap,Map<String, String> responseMap)
	{
		StringBuffer sb = new StringBuffer();
		HttpsURLConnection connection = null ; 
		// 连续请求多次
		for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++)
		{
			/* 起始时间戳 */
			long st = System.currentTimeMillis() ; 
			/* 结束时间戳 */
			long ed = 0 ; 
			BufferedReader br = null ; 
			BufferedWriter bw = null ;
			try
			{
				/*========https配置开始=========*/
				// Create a trust manager that does not validate certificate chains
				TrustManager[] trustAllCerts = new TrustManager[]
				{ new X509TrustManager()
				{
					public X509Certificate[] getAcceptedIssuers()
					{
						return null;
					}

					public void checkClientTrusted(X509Certificate[] certs, String authType)
					{
					}

					public void checkServerTrusted(X509Certificate[] certs, String authType)
					{
					}
				} };
				
				// Install the all-trusting trust manager
				SSLContext sc = SSLContext.getInstance("TLS");
				sc.init(null, trustAllCerts, new SecureRandom());
				HttpsURLConnection
						.setDefaultSSLSocketFactory(sc.getSocketFactory());
				/*========https配置结束=========*/
				/* 创建Url */
				URL url = new URL(urlStr);
				/* 获取链接 */
				connection = (HttpsURLConnection) this.newConnection(url, headerMap);
				connection.setHostnameVerifier(new TrustAnyHostnameVerifier());
				
				/* Post请求,必须加以下操作 */
				connection.setDoOutput(true);
				connection.setDoInput(true);
				connection.setRequestMethod("POST");

				/* 先向服务器写数据
				 * 如何将我们的参数写到输出流呢???
				 * 得遵循HTTP协议,看浏览器怎么做,我们也怎么做
				 * 
				 * URL get中的字符串
				 * method=submit&email=aaa&password=bbbb
				 *  */
				StringBuffer paramSb = new StringBuffer() ; 
				for (Iterator iterator = paramsMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + ""; 
					String value = me.getValue() + "" ;
					key = key.trim();
					value = value.trim() ; 
					if (key.equals(""))
					{
						paramSb.append(value);
					}else {
						paramSb.append(key + "=" + value + "&");
					}
				}

				if (paramSb.toString().endsWith("&"))
				{
					paramSb.delete(paramSb.length() - 1, paramSb.length());
				}
				
				/* 设置公共的请求头 */
				this.setCommonHeader(headerMap,connection);
				/* 设置请求头 */
				for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext();)
				{
					Entry me = (Entry) iterator.next();
					String key = me.getKey() + "" ; 
					String value = me.getValue() + "" ;
					key = key.trim() ; 
					value = value.trim() ; 
					if(!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE))
					{
						connection.setRequestProperty(key, value);
					}
				}
				
				bw = new BufferedWriter(new OutputStreamWriter(
						connection.getOutputStream()));
				bw.write(paramSb.toString());
				bw.flush();

				/* 获取网址对应的输入流和输出流 */
				InputStream is = connection.getInputStream() ;
				
				//响应码成功
				if(connection.getResponseCode() == 200)
				{
					br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
				}else
				{
					if(connection.getErrorStream() != null)
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}else
					{
						br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
					}
				}
				
				String line = "";
				while ((line = br.readLine()) != null)
				{
					sb.append(line.trim());
				}
				/* 存储响应头 */
				responseHeaderSave(headerMap,responseMap, connection);
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				//ConstatFinalUtil.SYS_LOGGER.info("响应体:{}",sb.toString());
				ConstatFinalUtil.SYS_LOGGER.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",i,(ed-st),urlStr,headerMap,paramsMap,responseMap);
				/* 检查网络 */
				this.noNetWork(true);
				/* 请求成功就退出 */
				break ;
			}catch(UnknownHostException | SocketTimeoutException e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
				/* 检查网络 */
				this.noNetWork(false);
			}catch (Exception e)
			{
				/* 结束时间戳 */
				ed = System.currentTimeMillis() ; 
				ConstatFinalUtil.SYS_LOGGER.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
						i,(ed-st),urlStr,headerMap,paramsMap,responseMap,e);
			}finally
			{
				/* 关闭流 */
				this.fileUtil.closeCharAll(br, null);
			}
			
			//重试机制
			if("false".equalsIgnoreCase(headerMap.get("retry")))
			{
				/* 默认不重试 */
				break ; 
			}
		}
		return sb.toString();
	}
	
	/**
	 * 木有网络如何处理
	 * netFlag:false,木有链接上网络;true:成功链接上网络
	 */
	private void noNetWork(boolean netFlag)
	{
		if(netFlag)
		{
			ConstatFinalUtil.networkCount = 0 ;
		}else
		{
			ConstatFinalUtil.networkCount = ConstatFinalUtil.networkCount + 1 ; 
			if(ConstatFinalUtil.networkCount >= ConstatFinalUtil.CONFIG_JSON.getIntValue("network.error.totalCount"))
			{
				/* 要采取措施,要切换ip
				 * 如果服务器无法上网,发送通知邮件
				 *  */
				boolean ipFlag = false ;
				//boolean ipFlag = this.commandUtil.switchIp("", "");
				JSONArray accountsArr = (JSONArray) ConstatFinalUtil.CONFIG_JSON.get("email.accounts");
				/* 标题 */
				String subject = ConstatFinalUtil.CONFIG_JSON.getString("email.subject") ; 
				/* 内容 */
				String text = ConstatFinalUtil.CONFIG_JSON.getString("email.content") ; 
				int totalCount = accountsArr.size() ;
				int succedCount = 0 ; 
				int failedCount = 0 ; 
				for (Iterator iterator = accountsArr.iterator(); iterator.hasNext();)
				{
					String email = (String) iterator.next();
					boolean emailFlag = this.springEmailUtil.sendHTMLMail(email, subject, text) ; 
					if(emailFlag)
					{
						succedCount ++ ; 
						if(!ipFlag)
						{
							ipFlag = true ;
						}
					}else
					{
						failedCount ++ ; 
					}
				}
				ConstatFinalUtil.SYS_LOGGER.error("无法上网,需要发送邮件;邮件人数:{},成功人数:{},失败人数:{}",totalCount,succedCount,failedCount);
//				if(ipFlag)
//				{
//					ConstatFinalUtil.networkCount = 0 ;
//				}
				ConstatFinalUtil.networkCount = 0 ;
			}
		}
		ConstatFinalUtil.SYS_LOGGER.error("连网标志:{},失败次数:{}",netFlag,ConstatFinalUtil.networkCount);
	}

	/**
	 * 存储响应头
	 * @param responseMap
	 * @param connection
	 * @throws IOException 
	 */
	public void responseHeaderSave(Map<String,String> headerMap,Map<String, String> responseMap, HttpURLConnection connection) throws IOException
	{
		if(connection != null)
		{
			responseMap.put("code", connection.getResponseCode() + "") ;
			/* 把响应头里面的内容放到请求头里面 */
			Map<String, List<String>> headerFieldsMap = connection.getHeaderFields() ; 
			for (Iterator iterator = headerFieldsMap.entrySet().iterator(); iterator.hasNext();)
			{
				Entry me = (Entry) iterator.next();
				String key = me.getKey() + "" ; 
				List<String> valList = (List<String>) me.getValue() ; 
				StringBuffer valSb = new StringBuffer();
				for (Iterator iterator2 = valList.iterator(); iterator2.hasNext();)
				{
					String valTemp = (String) iterator2.next();
					valSb.append(valTemp + ConstatFinalUtil.SPLIT_STR);
				}
				responseMap.put(key, valSb.toString());
			}
		}
		
		/* 处理目标的Cookie */
		String cookieTarget = responseMap.get("Set-Cookie") ; 
		String domain = headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "domain");
		/* 处理Cookie */
		Map<String, String> resultMap = new HashMap<String, String>();
		/* 处理原始的Cookie,饼干插件需要的 */
		JSONArray cookieArr = this.proccedCookieResponse(cookieTarget, domain, resultMap);
		responseMap.put("cookieArr", cookieArr.toJSONString());
		/* 合并Cookie */
		String cookieRes = resultMap.get("cookieRes");
		List<String> keySearchList = new ArrayList<String>();
		List<String> valueSearchList = new ArrayList<String>();
		/* 合并Cookie */
		cookieRes = this.cookieMerge(headerMap, cookieRes, keySearchList, valueSearchList);
		/* 存储处理过以后的Cookie */
		responseMap.put("cookieTarget", cookieRes);
	}
	
	/**
	 * 设置代理
	 * @throws xception 
	 */
	private URLConnection newConnection(URL url,Map<String, String> headerMap) throws Exception
	{
		if("true".equalsIgnoreCase(headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "proxy")))
		{
			String ip = headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "ip") ; 
			int port = Integer.valueOf(headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "port"));
			Proxy proxy = new Proxy(Type.SOCKS, new InetSocketAddress(ip, port));
			
			/* 移除代理 */
			headerMap.remove(ConstatFinalUtil.REQ_HEADER_IGNORE + "proxy");
			headerMap.remove(ConstatFinalUtil.REQ_HEADER_IGNORE + "ip");
			headerMap.remove(ConstatFinalUtil.REQ_HEADER_IGNORE + "port");
			/* 设置代理 */
			return url.openConnection(proxy);
		}else
		{
			return url.openConnection() ;
		}
	}
	
	/**
	 * 设置公共的请求头
	 * @param headerMap
	 */
	public void setCommonHeader(Map<String, String> headerMap,URLConnection connection)
	{
		String readTimeout = ConstatFinalUtil.REQ_HEADER_IGNORE + "read_timeout" ; 
		if(headerMap.get(readTimeout) != null)
		{
			/* 设置读取超时 */
			connection.setReadTimeout(Integer.valueOf(headerMap.get(readTimeout)));
		}else
		{
			connection.setReadTimeout(ConstatFinalUtil.READ_TIMEOUT);
		}
		String reqConnectTimeout = ConstatFinalUtil.REQ_HEADER_IGNORE + "req_connect_timeout" ; 
		if(headerMap.get(reqConnectTimeout) != null)
		{
			/* 设置请求超时 */
			connection.setConnectTimeout(Integer.valueOf(headerMap.get(reqConnectTimeout)));
		}else
		{
			connection.setConnectTimeout(ConstatFinalUtil.REQ_CONNECT_TIMEOUT);
		}
		
		/* 去掉那些包含关键字的cookei */
		String cookieRes = "" ; 
		List<String> keyList = new ArrayList<String>();
		List<String> valList = new ArrayList<String>();
		cookieRes = this.cookieMerge(headerMap, cookieRes,keyList,valList);
		headerMap.put("cookie", cookieRes);
	}
	
	/**
	 * 生成一个新的Cookie
	 * @return
	 */
	public String newCookieStr(String path)
	{
		String cookie = "JSESSIONID="+ UUID.randomUUID().toString() ; 
		return cookie ;
//		String sufix = ";Path="+ path +"; HttpOnly";
//		return cookie + sufix ; 
	}
	
	/**
	 * 传入请求头的Cookie和响应头的Cookie,合并一下
	 * 如果cookieRes要是木有值,就和Cookie一样就可以
	 * @return
	 */
	public String cookieMerge(Map<String, String> headerMap,String cookieRes,
			List<String> keySearchList,List<String> valueSearchList)
	{
		/* 判断值 */
		String searchStr = "deleted";
		/* 判断键 */
		//String keySearch = "checkpoint" ;
		
		valueSearchList.add(searchStr);
		//keySearchList.add(keySearch);
		/* 最终的Cookie
		 * fr=aa;sb=bb;fr=delete
		 *  */
		String cookieHeader = headerMap.get("cookie");
		if(cookieHeader == null || "".equalsIgnoreCase(cookieHeader))
		{
			/* 如果目标的cookie要是木有值,直接和原来的cookie一样 */
			cookieHeader = this.newCookieStr("/") ; 
		}
		
		if(cookieRes == null || "".equalsIgnoreCase(cookieRes))
		{
			/* 如果目标的cookie要是木有值,直接和原来的cookie一样 */
			cookieRes = cookieHeader ; 
		}
		
		Map<String, String> cookieHeaderMap = this.cookieSplit(cookieHeader);
		/* 响应头中的Cookie */
		Map<String, String> cookieResMap = this.cookieSplit(cookieRes);
		/* 找出响应头中Cookie带delete字样的 */
		for (Iterator iterator = cookieResMap.entrySet().iterator(); iterator.hasNext();)
		{
			Entry me = (Entry) iterator.next();
			String key = me.getKey() + "" ; 
			String value = me.getValue() + "" ; 
			key = key.trim() ; 
			value = value.trim() ; 
			if(keySearchList.contains(key) || valueSearchList.contains(value))
			{
				/* 说明已经删除了 */
				cookieHeaderMap.remove(key);
			}else
			{
				cookieHeaderMap.put(key,value);
			}
		}
		/* 拼装最终想要的Cookie */
		StringBuffer sb = new StringBuffer();
		for (Iterator iterator = cookieHeaderMap.entrySet().iterator(); iterator.hasNext();)
		{
			Entry me = (Entry) iterator.next();
			String key = me.getKey() + "" ; 
			String value = me.getValue() + "" ; 
			sb.append(key.trim() + "=" + value.trim() + ";");
		}
		return sb.toString() ; 
	}
	
	/**
	 * Cookie拆分
	 * @param headerMap
	 * @param keyword
	 * @return
	 */
	public Map<String, String> cookieSplit(String cookie)
	{
		Map<String, String> resultMap = new HashMap<String, String>();
		if(cookie != null && !"".equalsIgnoreCase(cookie))
		{
			/* 切分Cookie */
			String[] cookies = cookie.split(";");
			for (int i = 0; i < cookies.length; i++)
			{
				String cookieTemp = cookies[i];
				String[] splits = cookieTemp.split("=");
				if(splits.length == 2)
				{
					resultMap.put(splits[0].trim(), splits[1].trim());
				}
			}
		}
		return resultMap;
	}
	
	/**
	 * 处理服务器响应端的Cookie
	 * @param cookieRes	存储Cookie的结果
	 * @param cookie	响应的Cookie格式的字符串
	 * @param domain cookie的域名
	 * @return	拼装成饼干插件需要的JSON
	 */
	public JSONArray proccedCookieResponse(String cookie,String domain,Map<String, String> resultMap)
	{
		String cookieRes = "" ; 
		JSONArray cookieArr = new JSONArray();
		if(cookie != null)
		{
			String[] cookies = cookie.split(ConstatFinalUtil.SPLIT_STR_ZHUAN);
			for (int i = 0; i < cookies.length; i++)
			{
				/* 原装的Cookie */
				String cookieTemp = cookies[i];
				/* 拼装json */
				JSONObject cookieTempJSON = this.proccedCookieJSON(cookieTemp,domain);
				cookieTempJSON.put("id", i + 1);
				
				/* 目标的json */
				String cookieTarTemp = cookieTempJSON.getString("name") + "=" +  cookieTempJSON.getString("value") + ";";
				/* 拼装json */
				cookieRes = cookieRes + cookieTarTemp;
				cookieArr.add(cookieTempJSON);
			}
		}
		resultMap.put("cookieRes", cookieRes);
		return cookieArr;
	}
	
	/**
	 * 生成一个饼开插件的json
{
    "domain": ".facebook.com",
    "expirationDate": 1599095052.94666,
    "hostOnly": false,
    "httpOnly": false,
    "name": "c_user",
    "path": "/",
    "sameSite": "no_restriction",
    "secure": true,
    "session": false,
    "storeId": "0",
    "value": "100040966342079",
    "id": 1
}
	 * @return
	 */
	private JSONObject proccedCookieJSON(String val,String domain)
	{
		Map<String, String> cookieMap = this.cookieSplit(val);
		/* 把第一行的cookie,变成Map */
		String name = "";
		String equalsIndex = "=" ; 
		if(val.indexOf(equalsIndex) != -1)
		{
			name = val.substring(0, val.indexOf(equalsIndex)) ;
		}
		JSONObject resultJSON = new JSONObject();
		resultJSON.put("domain", domain);
		/* 有效期为一天;单位是秒 */
		long maxAge = 1000 ; 
		if(cookieMap.get("Max-Age") != null)
		{
			maxAge = Long.valueOf(cookieMap.get("Max-Age") + "");
		}
		resultJSON.put("expirationDate", System.currentTimeMillis() / 1000 + maxAge);
		/* hostOnly  */
		String hostOnly = "hostOnly" ;
		if(cookieMap.get(hostOnly) != null)
		{
			resultJSON.put(hostOnly, true);
		}else
		{
			resultJSON.put(hostOnly, false);
		}
		
		/* httpOnly  */
		String httpOnly = "httpOnly" ;
		if(cookieMap.get(httpOnly) != null)
		{
			resultJSON.put(httpOnly, true);
		}else
		{
			resultJSON.put(httpOnly, false);
		}
		/* secure  */
		String secure = "secure" ;
		if(cookieMap.get(secure) != null)
		{
			resultJSON.put(secure, true);
		}else
		{
			resultJSON.put(secure, false);
		}
		/* session  */
		String session = "session" ;
		if(cookieMap.get(session) != null)
		{
			resultJSON.put(session, true);
		}else
		{
			resultJSON.put(session, false);
		}
		
		resultJSON.put("name", name);
		String value = cookieMap.get(name) ; 
		resultJSON.put("value",  value);
		resultJSON.put("path", "/" );
		resultJSON.put("sameSite", "no_restriction" );
		resultJSON.put("storeId", "0" );
		return resultJSON ; 
	}
	
	/**
	 * 设置代理
	 * @param headerMap
	 */
	public void setProxy(Map<String, String> headerMap)
	{
		/* 设置代理 */
//		headerMap.put(ConstatFinalUtil.REQ_HEADER_IGNORE + "proxy", "true");
//		headerMap.put(ConstatFinalUtil.REQ_HEADER_IGNORE + "ip", "192.168.100.6");
//		headerMap.put(ConstatFinalUtil.REQ_HEADER_IGNORE + "port", "48333");
	}
}